import * as THREE from "three"
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import { Water } from "three/examples/jsm/objects/Water";
import { Sky } from "three/examples/jsm/objects/Sky";
interface initGeometryOption {
    geometryOption: {
        name: string,
        sizes?: number[],
        option?: Array<any>,
        vertices?: Array<number>
    },
    materialOption: {
        name: string,
        color?: number | string,
        opacity?: number,
        transparent?: boolean,
        specular?: string,
        shininess?: number,
        size?: number,
        side?: any,
        wireframe?: any
    },
    objectName?: string,
    beforeAdd?: Function | null
}

class Box {
    private scene;
    private camera;
    private renderer;
    private container;
    private planet;     //星球
    private ring;       //轨道环
    private stars;      //星星
    private satellite;  //卫星

    constructor() { }
    init(container) {
        this.container = container;

        // 设置渲染器
        this.setRender();
        // 初始化场景
        this.setScene();
        // 设置相机    
        this.setCamera();
        // 启动渲染
        this.render();
        // 动作监听
        this.addControl();
    }
    // 场景
    setScene() {
        this.scene = new THREE.Scene();
        this.scene.background = "#000000";

        //初始化模型
        this.initObjects();

        // //点光源
        this.createLight("PointLight", "#ffffff", (point) => point.position.set(200, 300, 400));

        // // 点光源2  位置和point关于原点对称
        this.createLight("PointLight", "#ffffff", (point) => point.position.set(-400, -200, -300));

        // //环境光
        this.createLight("AmbientLight", "#444444");

        // 创建坐标系
        this.createAxis();
    }
    initObjects() {
        //创建星球
        let geometry = new THREE.SphereGeometry(80, 32, 32);//创建一个球
        let material = new THREE.MeshLambertMaterial({
            color: "#03c03c",
            wireframe: true //开启线条
        });
        this.planet = new THREE.Mesh(geometry, material);
        this.scene.add(this.planet);

        // 创建星球轨道环
        const TorusGeometry = new THREE.TorusGeometry(150, 10, 2, 120);
        const TorusMaterial = new THREE.MeshLambertMaterial({
            color: 0x40a9ff,
            wireframe: true
        });
        this.ring = new THREE.Mesh(TorusGeometry, TorusMaterial);
        this.ring.rotation.x = Math.PI / 2;
        this.scene.add(this.ring);

        // 创建卫星
        const IcoGeometry = new THREE.IcosahedronGeometry(16, 0);//二十面几何体
        const IcoMaterial = new THREE.MeshToonMaterial({ color: 0xfffc00 });
        this.satellite = new THREE.Mesh(IcoGeometry, IcoMaterial);
        // this.satellite.position.set(100, 100, -100);
        this.scene.add(this.satellite);

        // 创建星星
        this.stars = new THREE.Group();
        for (let i = 0; i < 500; i++) {
            let star = new THREE.IcosahedronGeometry(Math.random() * 2, 0);    //二十面几何体
            let material = new THREE.MeshToonMaterial({ color: 0xeeeeee });
            let mesh = new THREE.Mesh(star, material);
            mesh.position.x = (Math.random() - 0.5) * 700;
            mesh.position.y = (Math.random() - 0.5) * 700;
            mesh.position.z = (Math.random() - 0.5) * 700;
            mesh.rotation.x = Math.random() * 2 * Math.PI;
            mesh.rotation.y = Math.random() * 2 * Math.PI;
            mesh.rotation.z = Math.random() * 2 * Math.PI;
            this.stars.add(mesh)
        }
        this.scene.add(this.stars);
    }
    // 相机
    setCamera() {
        var width = this.container.offsetWidth; //窗口宽度
        var height = this.container.offsetHeight; //窗口高度
        var k = width / height; //窗口宽高比
        var s = 40; //三维场景显示范围控制系数，系数越大，显示的范围越大
        //创建相机对象
        this.camera = new THREE.PerspectiveCamera(s, width / height, 0.1, 1000);
        this.camera.position.set(250, 250, 250); //设置相机位置
        this.camera.up.set(0, 1, 0); //设置相机位置
        this.camera.lookAt(this.scene.position); //设置相机方向(指向的场景对象)
    }
    // 渲染器
    setRender() {
        this.renderer = new THREE.WebGLRenderer();
        this.renderer.setSize(this.container.offsetWidth, this.container.offsetHeight);//设置渲染区域尺寸
        this.renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
        this.container.appendChild(this.renderer.domElement); //body元素中插入canvas对象

        this.pmremGenerator = new THREE.PMREMGenerator(this.renderer);
    }

    private axis = new THREE.Vector3(0, 0, 1);
    private rot = 0;
    // 渲染
    render() {
        this.renderer.render(this.scene, this.camera);
        // 给网格模型添加一个转动动画
        this.rot += Math.random() * 0.8;
        const radian = (this.rot * Math.PI) / 180;

        // 星球位置动画
        this.planet && (this.planet.rotation.y += .005);
        // 星球轨道环位置动画
        this.ring && this.ring.rotateOnAxis(this.axis, Math.PI / 400);
        // this.ring && (this.ring.rotation.z += .005); 同等效果
        // 卫星位置动画
        this.satellite.position.x = 250 * Math.sin(radian);
        this.satellite.position.y = 100 * Math.cos(radian);
        this.satellite.position.z = -100 * Math.cos(radian);
        this.satellite.rotation.x += 0.005;
        this.satellite.rotation.y += 0.005;
        this.satellite.rotation.z -= 0.005;
        // 星星动画
        this.stars.rotation.y += 0.0009;
        this.stars.rotation.z -= 0.0003;

        //监听鼠标、键盘事件
        requestAnimationFrame(this.render.bind(this));
    }
    // 鼠标和键盘事件
    private controls;
    addControl() {
        this.controls = new OrbitControls(this.camera, this.renderer.domElement);//创建控件对象
        this.controls.enableDamping = true;
    }
    // 创建光源
    createLight(name, color, beforeAdd = null) {
        var point = new THREE[name](color);
        beforeAdd && beforeAdd(point);
        this.scene.add(point); //点光源添加到场景中
    }
    // 创建坐标系
    createAxis() {
        //辅助坐标系  参数250表示坐标系大小，可以根据场景大小去设置
        var axisHelper = new THREE.AxesHelper(250);
        this.scene.add(axisHelper);
    }
}

export default Box;